home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cracking 2
/
Cracking II..iso
/
Kompresni & kodovaci programy
/
ucl-0.91
/
examples
/
uclpack.c
< prev
Wrap
C/C++ Source or Header
|
2000-02-23
|
17KB
|
634 lines
/* uclpack.c -- example program: a simple file packer
This file is part of the UCL real-time data compression library.
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
The UCL library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The UCL library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the UCL library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
markus.oberhumer@jk.uni-linz.ac.at
*/
/*************************************************************************
// NOTE: this is an example program, so do not use to backup your data
//
// This program lacks things like sophisticated file handling but is
// pretty complete regarding compression - it should provide a good
// starting point for adaption for you applications.
**************************************************************************/
#include <ucl/ucl.h>
#include "lutil.h"
static const char *progname = NULL;
static unsigned long total_in = 0;
static unsigned long total_out = 0;
static ucl_bool opt_debug = 0;
/* don't compute or verify checksum, always use fast decompressor */
static ucl_bool opt_fast = 0;
/* magic file header for compressed files */
static const unsigned char magic[7] =
{ 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x1a };
/*************************************************************************
// file IO
**************************************************************************/
ucl_uint xread(FILE *f, ucl_voidp buf, ucl_uint len, ucl_bool allow_eof)
{
ucl_uint l;
l = ucl_fread(f,buf,len);
if (l > len)
{
fprintf(stderr,"\nsomething's wrong with your C library !!!\n");
exit(1);
}
if (l != len && !allow_eof)
{
fprintf(stderr,"\nread error - premature end of file\n");
exit(1);
}
total_in += l;
return l;
}
ucl_uint xwrite(FILE *f, const ucl_voidp buf, ucl_uint len)
{
if (f != NULL && ucl_fwrite(f,buf,len) != len)
{
fprintf(stderr,"\nwrite error (disk full ?)\n");
exit(1);
}
total_out += len;
return len;
}
int xgetc(FILE *f)
{
unsigned char c;
xread(f,(ucl_bytep) &c,1,0);
return c;
}
void xputc(FILE *f, int c)
{
unsigned char cc = (unsigned char) c;
xwrite(f,(ucl_bytep) &cc,1);
}
/* read and write portable 32-bit integers */
ucl_uint32 xread32(FILE *f)
{
unsigned char b[4];
ucl_uint32 v;
xread(f,b,4,0);
v = (ucl_uint32) b[3] << 0;
v |= (ucl_uint32) b[2] << 8;
v |= (ucl_uint32) b[1] << 16;
v |= (ucl_uint32) b[0] << 24;
return v;
}
void xwrite32(FILE *f, ucl_uint32 v)
{
unsigned char b[4];
b[3] = (unsigned char) (v >> 0);
b[2] = (unsigned char) (v >> 8);
b[1] = (unsigned char) (v >> 16);
b[0] = (unsigned char) (v >> 24);
xwrite(f,b,4);
}
/* util */
static ucl_uint get_overhead(int method, ucl_uint size)
{
if (method == 0x2B || method == 0x2D)
return size / 8 + 256;
return 0;
}
static char method_name[64];
static ucl_bool set_method_name(int method, int level)
{
method_name[0] = 0;
if (level < 1 || level > 10)
return 0;
if (method == 0x2B)
sprintf(method_name,"NRV2B-99/%d", level);
else if (method == 0x2D)
sprintf(method_name,"NRV2D-99/%d", level);
else
return 0;
return 1;
}
/*************************************************************************
// compress
//
// possible improvement: we could use overlapping compression to
// save some memory - see overlap.c. This would require some minor
// changes in the decompression code as well, because if a block
// turns out to be incompressible we would still have to store it in its
// compressed (slightly enlarged) form because the original (uncompressed)
// data would have been lost during the overlapping compression.
**************************************************************************/
int do_compress(FILE *fi, FILE *fo, int method, int level, ucl_uint block_size)
{
int r = 0;
ucl_byte *in = NULL;
ucl_byte *out = NULL;
ucl_uint in_len;
ucl_uint out_len;
ucl_uint32 flags = opt_fast ? 0 : 1;
ucl_uint32 checksum;
ucl_uint overhead = 0;
total_in = total_out = 0;
/*
* Step 1: write magic header, flags & block size, init checksum
*/
xwrite(fo,magic,sizeof(magic));
xwrite32(fo,flags);
xputc(fo,method); /* compression method */
xputc(fo,level); /* compression level */
xwrite32(fo,block_size);
checksum = ucl_adler32(0,NULL,0);
/*
* Step 2: allocate compression buffers and work-memory
*/
overhead = get_overhead(method,block_size);
in = ucl_malloc(block_size);
out = ucl_malloc(block_size + overhead);
if (in == NULL || out == NULL)
{
printf("%s: out of memory\n", progname);
r = 1;
goto err;
}
/*
* Step 3: process blocks
*/
for (;;)
{
/* read block */
in_len = xread(fi,in,block_size,1);
if (in_len <= 0)
break;
/* update checksum */
if (flags & 1)
checksum = ucl_adler32(checksum,in,in_len);
/* compress block */
r = UCL_E_ERROR;
if (method == 0x2B)
r = ucl_nrv2b_99_compress(in,in_len,out,&out_len,0,level,NULL,NULL);
else if (method == 0x2D)
r = ucl_nrv2d_99_compress(in,in_len,out,&out_len,0,level,NULL,NULL);
if (r != UCL_E_OK || out_len > in_len + get_overhead(method,in_len))
{
/* this should NEVER happen */
printf("internal error - compression failed: %d\n", r);
r = 2;
goto err;
}
/* write uncompressed block size */
xwrite32(fo,in_len);
if (out_len < in_len)
{
/* write compressed block */
xwrite32(fo,out_len);
xwrite(fo,out,out_len);
}
else
{
/* not compressible - write uncompressed block */
xwrite32(fo,in_len);
xwrite(fo,in,in_len);
}
}
/* write EOF marker */
xwrite32(fo,0);
/* write checksum */
if (flags & 1)
xwrite32(fo,checksum);
r = 0;
err:
ucl_free(out);
ucl_free(in);
return r;
}
/*************************************************************************
// decompress / test
//
// We are using overlapping (in-place) decompression to save some
// memory - see overlap.c.
**************************************************************************/
int do_decompress(FILE *fi, FILE *fo)
{
int r = 0;
ucl_byte *buf = NULL;
ucl_uint buf_len;
unsigned char m [ sizeof(magic) ];
ucl_uint32 flags;
int method;
int level;
ucl_uint block_size;
ucl_uint32 checksum;
ucl_uint overhead = 0;
total_in = total_out = 0;
/*
* Step 1: check magic header, read flags & block size, init checksum
*/
if (xread(fi,m,sizeof(magic),1) != sizeof(magic) ||
memcmp(m,magic,sizeof(magic)) != 0)
{
printf("%s: header error - this file is not compressed by uclpack\n", progname);
r = 1;
goto err;
}
flags = xread32(fi);
method = xgetc(fi);
level = xgetc(fi);
block_size = xread32(fi);
overhead = get_overhead(method,block_size);
if (overhead == 0 || !set_method_name(method, level))
{
printf("%s: header error - invalid method %d (level %d)\n",
progname, method, level);
r = 2;
goto err;
}
if (block_size < 1024 || block_size > 8*1024*1024L)
{
printf("%s: header error - invalid blo